import tkinter as tk
from tkinter import messagebox, ttk
from datetime import datetime
import csv
import json
from pathlib import Path


class StudentManagerApp:
    """学生管理系统"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("学生管理系统")
        self.root.geometry("900x600")
        self.root.resizable(False, False)
        
        # 居中显示窗口
        self.center_window()
        
        # 学生数据列表
        self.students = []
        
        # 正在修改的学生学号（用于标识修改模式）
        self.editing_student_id = None
        
        # 数据文件路径
        self.data_file = Path(__file__).parent / "students_data.json"
        
        # 加载已有数据
        self.load_data()
        
        # 创建UI
        self.create_widgets()
        
        # 刷新显示
        self.refresh_table()
    
    def center_window(self):
        """使窗口居中显示"""
        self.root.update_idletasks()
        width = self.root.winfo_width()
        height = self.root.winfo_height()
        x = (self.root.winfo_screenwidth() // 2) - (width // 2)
        y = (self.root.winfo_screenheight() // 2) - (height // 2)
        self.root.geometry(f'{width}x{height}+{x}+{y}')
    
    def create_widgets(self):
        """创建界面组件"""
        # 左侧：信息录入区域
        left_frame = tk.Frame(self.root, padx=20, pady=20)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH)
        
        # 录入表单
        form_frame = tk.LabelFrame(
            left_frame,
            text="学生信息录入",
            font=("Arial", 11, "bold"),
            padx=15,
            pady=15
        )
        form_frame.pack(fill=tk.BOTH, expand=True)
        
        # 学号
        tk.Label(form_frame, text="学号：", font=("Arial", 10), width=8, anchor="w").grid(row=0, column=0, sticky="w", pady=8)
        self.student_id_entry = tk.Entry(form_frame, font=("Arial", 10), width=20)
        self.student_id_entry.grid(row=0, column=1, pady=8, padx=5)
        
        # 姓名
        tk.Label(form_frame, text="姓名：", font=("Arial", 10), width=8, anchor="w").grid(row=1, column=0, sticky="w", pady=8)
        self.name_entry = tk.Entry(form_frame, font=("Arial", 10), width=20)
        self.name_entry.grid(row=1, column=1, pady=8, padx=5)
        
        # 性别
        tk.Label(form_frame, text="性别：", font=("Arial", 10), width=8, anchor="w").grid(row=2, column=0, sticky="w", pady=8)
        self.gender_var = tk.StringVar(value="男")
        gender_frame = tk.Frame(form_frame)
        gender_frame.grid(row=2, column=1, sticky="w", pady=8, padx=5)
        tk.Radiobutton(gender_frame, text="男", variable=self.gender_var, value="男", font=("Arial", 10)).pack(side=tk.LEFT, padx=5)
        tk.Radiobutton(gender_frame, text="女", variable=self.gender_var, value="女", font=("Arial", 10)).pack(side=tk.LEFT, padx=5)
        
        # 年龄
        tk.Label(form_frame, text="年龄：", font=("Arial", 10), width=8, anchor="w").grid(row=3, column=0, sticky="w", pady=8)
        self.age_entry = tk.Entry(form_frame, font=("Arial", 10), width=20)
        self.age_entry.grid(row=3, column=1, pady=8, padx=5)
        
        # 班级
        tk.Label(form_frame, text="班级：", font=("Arial", 10), width=8, anchor="w").grid(row=4, column=0, sticky="w", pady=8)
        self.class_entry = tk.Entry(form_frame, font=("Arial", 10), width=20)
        self.class_entry.grid(row=4, column=1, pady=8, padx=5)
        
        # 联系电话
        tk.Label(form_frame, text="联系电话：", font=("Arial", 10), width=8, anchor="w").grid(row=5, column=0, sticky="w", pady=8)
        self.phone_entry = tk.Entry(form_frame, font=("Arial", 10), width=20)
        self.phone_entry.grid(row=5, column=1, pady=8, padx=5)
        
        # 备注
        tk.Label(form_frame, text="备注：", font=("Arial", 10), width=8, anchor="w").grid(row=6, column=0, sticky="nw", pady=8)
        self.remark_text = tk.Text(form_frame, font=("Arial", 10), width=20, height=3)
        self.remark_text.grid(row=6, column=1, pady=8, padx=5)
        
        # 按钮区域
        button_frame = tk.Frame(left_frame)
        button_frame.pack(pady=20)
        
        tk.Button(
            button_frame,
            text="添加学生",
            command=self.add_student,
            padx=15,
            pady=8,
            bg="#4CAF50",
            fg="black",
            font=("Arial", 10, "bold"),
            cursor="hand2",
            width=12
        ).pack(side=tk.LEFT, padx=5)
        
        tk.Button(
            button_frame,
            text="清空表单",
            command=self.clear_form,
            padx=15,
            pady=8,
            bg="#FF9800",
            fg="black",
            font=("Arial", 10, "bold"),
            cursor="hand2",
            width=12
        ).pack(side=tk.LEFT, padx=5)
        
        # 右侧：学生列表区域
        right_frame = tk.Frame(self.root, padx=20, pady=20)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        # 顶部操作按钮
        top_button_frame = tk.Frame(right_frame)
        top_button_frame.pack(fill=tk.X, pady=(0, 10))
        
        tk.Label(
            top_button_frame,
            text="学生列表",
            font=("Arial", 12, "bold")
        ).pack(side=tk.LEFT)
        
        self.count_label = tk.Label(
            top_button_frame,
            text="(共0人)",
            font=("Arial", 10),
            fg="#666"
        )
        self.count_label.pack(side=tk.LEFT, padx=10)
        
        tk.Button(
            top_button_frame,
            text="删除选中",
            command=self.delete_student,
            padx=10,
            pady=5,
            bg="#F44336",
            fg="black",
            font=("Arial", 9, "bold"),
            cursor="hand2"
        ).pack(side=tk.RIGHT, padx=2)
        
        tk.Button(
            top_button_frame,
            text="清空全部",
            command=self.clear_all_students,
            padx=10,
            pady=5,
            bg="#E91E63",
            fg="black",
            font=("Arial", 9, "bold"),
            cursor="hand2"
        ).pack(side=tk.RIGHT, padx=2)
        
        tk.Button(
            top_button_frame,
            text="修改",
            command=self.edit_student,
            padx=10,
            pady=5,
            bg="#2196F3",
            fg="black",
            font=("Arial", 9, "bold"),
            cursor="hand2"
        ).pack(side=tk.RIGHT, padx=2)
        
        tk.Button(
            top_button_frame,
            text="导出Excel",
            command=self.export_to_excel,
            padx=10,
            pady=5,
            bg="#4CAF50",
            fg="black",
            font=("Arial", 9, "bold"),
            cursor="hand2"
        ).pack(side=tk.RIGHT, padx=2)
        
        # 表格区域
        table_frame = tk.Frame(right_frame)
        table_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建滚动条
        scrollbar_y = tk.Scrollbar(table_frame)
        scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)
        
        scrollbar_x = tk.Scrollbar(table_frame, orient=tk.HORIZONTAL)
        scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 创建表格
        columns = ("学号", "姓名", "性别", "年龄", "班级", "联系电话", "备注")
        self.tree = ttk.Treeview(
            table_frame,
            columns=columns,
            show="headings",
            yscrollcommand=scrollbar_y.set,
            xscrollcommand=scrollbar_x.set,
            height=20
        )
        
        # 设置列宽和对齐方式
        self.tree.column("学号", width=100, anchor="center")
        self.tree.column("姓名", width=80, anchor="center")
        self.tree.column("性别", width=50, anchor="center")
        self.tree.column("年龄", width=50, anchor="center")
        self.tree.column("班级", width=100, anchor="center")
        self.tree.column("联系电话", width=120, anchor="center")
        self.tree.column("备注", width=150, anchor="w")
        
        # 设置表头
        for col in columns:
            self.tree.heading(col, text=col)
        
        self.tree.pack(fill=tk.BOTH, expand=True)
        
        scrollbar_y.config(command=self.tree.yview)
        scrollbar_x.config(command=self.tree.xview)
        
        # 绑定表格选中事件
        self.tree.bind('<<TreeviewSelect>>', self.on_student_select)
        
        # 状态栏
        self.status_label = tk.Label(
            self.root,
            text="就绪",
            font=("Arial", 9),
            fg="#666",
            anchor="w",
            padx=10,
            pady=5,
            relief=tk.SUNKEN
        )
        self.status_label.pack(side=tk.BOTTOM, fill=tk.X)
    
    def on_student_select(self, event):
        """表格选中事件 - 自动填充学生信息到表单"""
        selected = self.tree.selection()
        if not selected:
            return
        
        # 获取选中的学生信息
        item = self.tree.item(selected[0])
        student_id = str(item["values"][0])
        
        # 找到对应的学生
        for student in self.students:
            if str(student["学号"]) == student_id:
                # 填充到表单（仅显示，不进入修改模式）
                self.student_id_entry.config(state=tk.NORMAL)
                self.student_id_entry.delete(0, tk.END)
                self.student_id_entry.insert(0, student["学号"])
                
                self.name_entry.delete(0, tk.END)
                self.name_entry.insert(0, student["姓名"])
                
                self.gender_var.set(student["性别"])
                
                self.age_entry.delete(0, tk.END)
                self.age_entry.insert(0, student["年龄"])
                
                self.class_entry.delete(0, tk.END)
                self.class_entry.insert(0, student["班级"])
                
                self.phone_entry.delete(0, tk.END)
                self.phone_entry.insert(0, student["联系电话"])
                
                self.remark_text.delete("1.0", tk.END)
                self.remark_text.insert("1.0", student["备注"])
                
                self.status_label.config(text=f"已选中学生：{student['姓名']}，点击'修改'按钮进入编辑模式", fg="#666")
                break
    
    def add_student(self):
        """添加学生"""
        # 获取表单数据
        student_id = self.student_id_entry.get().strip()
        name = self.name_entry.get().strip()
        gender = self.gender_var.get()
        age = self.age_entry.get().strip()
        class_name = self.class_entry.get().strip()
        phone = self.phone_entry.get().strip()
        remark = self.remark_text.get("1.0", tk.END).strip()
        
        # 验证必填项
        if not student_id:
            messagebox.showwarning("提示", "请输入学号！")
            self.student_id_entry.focus()
            return
        
        if not name:
            messagebox.showwarning("提示", "请输入姓名！")
            self.name_entry.focus()
            return
        
        # 验证年龄是否为数字
        if age:
            try:
                age_int = int(age)
                if age_int < 0 or age_int > 150:
                    messagebox.showwarning("提示", "年龄范围不合理！")
                    self.age_entry.focus()
                    return
            except ValueError:
                messagebox.showwarning("提示", "年龄必须是数字！")
                self.age_entry.focus()
                return
        
        # 如果是修改模式，先删除旧记录
        if self.editing_student_id is not None:
            self.students = [s for s in self.students if str(s["学号"]) != str(self.editing_student_id)]
            self.editing_student_id = None
        else:
            # 检查学号是否已存在（只在添加新学生时检查）
            for student in self.students:
                if str(student["学号"]) == student_id:
                    messagebox.showwarning("提示", f"学号 {student_id} 已存在！")
                    self.student_id_entry.focus()
                    return
        
        # 添加到列表
        student = {
            "学号": student_id,
            "姓名": name,
            "性别": gender,
            "年龄": age,
            "班级": class_name,
            "联系电话": phone,
            "备注": remark
        }
        
        self.students.append(student)
        
        # 保存数据
        self.save_data()
        
        # 刷新表格
        self.refresh_table()
        
        # 清空表单
        self.clear_form()
        
        # 提示
        self.status_label.config(text=f"成功添加学生：{name}", fg="#4CAF50")
        messagebox.showinfo("成功", f"学生 {name} 添加成功！")
    
    def clear_form(self):
        """清空表单"""
        self.student_id_entry.delete(0, tk.END)
        self.student_id_entry.config(state=tk.NORMAL)  # 恢复学号输入框状态
        self.name_entry.delete(0, tk.END)
        self.gender_var.set("男")
        self.age_entry.delete(0, tk.END)
        self.class_entry.delete(0, tk.END)
        self.phone_entry.delete(0, tk.END)
        self.remark_text.delete("1.0", tk.END)
        self.student_id_entry.focus()
        self.editing_student_id = None  # 清除修改模式标记
    
    def refresh_table(self):
        """刷新表格显示"""
        # 清空表格
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # 添加数据
        for student in self.students:
            self.tree.insert("", tk.END, values=(
                student["学号"],
                student["姓名"],
                student["性别"],
                student["年龄"],
                student["班级"],
                student["联系电话"],
                student["备注"]
            ))
        
        # 更新计数
        self.count_label.config(text=f"(共{len(self.students)}人)")
    
    def delete_student(self):
        """删除选中的学生"""
        selected = self.tree.selection()
        
        if not selected:
            messagebox.showwarning("提示", "请先在表格中点击选中要删除的学生！")
            return
        
        # 获取选中的学生信息
        item = self.tree.item(selected[0])
        student_id = str(item["values"][0])  # 转换为字符串进行匹配
        name = str(item["values"][1])
        
        # 确认删除
        result = messagebox.askyesno("确认删除", f"确定要删除学生 {name}（学号：{student_id}）吗？")
        
        if result:
            # 从列表中删除（确保学号类型一致）
            self.students = [s for s in self.students if str(s["学号"]) != student_id]
            
            # 保存数据
            self.save_data()
            
            # 刷新表格
            self.refresh_table()
            
            self.status_label.config(text=f"已删除学生：{name}", fg="#F44336")
            messagebox.showinfo("删除成功", f"学生 {name} 已被删除！")
    
    def edit_student(self):
        """修改学生信息"""
        selected = self.tree.selection()
        if not selected:
            messagebox.showwarning("提示", "请先选择要修改的学生！")
            return
        
        # 获取选中的学生信息
        item = self.tree.item(selected[0])
        student_id = str(item["values"][0])  # 转换为字符串
        
        # 找到对应的学生
        for student in self.students:
            if str(student["学号"]) == student_id:
                # 填充到表单
                self.student_id_entry.config(state=tk.NORMAL)  # 先解锁
                self.student_id_entry.delete(0, tk.END)
                self.student_id_entry.insert(0, student["学号"])
                self.student_id_entry.config(state=tk.DISABLED)  # 学号不可修改
                
                self.name_entry.delete(0, tk.END)
                self.name_entry.insert(0, student["姓名"])
                
                self.gender_var.set(student["性别"])
                
                self.age_entry.delete(0, tk.END)
                self.age_entry.insert(0, student["年龄"])
                
                self.class_entry.delete(0, tk.END)
                self.class_entry.insert(0, student["班级"])
                
                self.phone_entry.delete(0, tk.END)
                self.phone_entry.insert(0, student["联系电话"])
                
                self.remark_text.delete("1.0", tk.END)
                self.remark_text.insert("1.0", student["备注"])
                
                # 标记为修改模式（不删除原记录）
                self.editing_student_id = student_id
                
                self.status_label.config(text=f"正在修改学生信息：{student['姓名']}，修改后点击'添加学生'保存", fg="#2196F3")
                break
    
    def export_to_excel(self):
        """导出为Excel（CSV格式）"""
        if not self.students:
            messagebox.showwarning("提示", "没有学生数据可导出！")
            return
        
        # 生成文件名
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"学生信息表_{timestamp}.csv"
        filepath = Path(__file__).parent / filename
        
        try:
            # 写入CSV文件
            with open(filepath, 'w', encoding='utf-8-sig', newline='') as f:
                writer = csv.DictWriter(f, fieldnames=["学号", "姓名", "性别", "年龄", "班级", "联系电话", "备注"])
                writer.writeheader()
                writer.writerows(self.students)
            
            self.status_label.config(text=f"导出成功：{filename}", fg="#4CAF50")
            
            result = messagebox.showinfo(
                "导出成功",
                f"学生信息已导出到：\n{filepath}\n\n共导出 {len(self.students)} 条记录\n\n是否打开文件所在文件夹？"
            )
            
            if result == 'ok':
                import os
                os.system(f'open "{filepath.parent}"')
        
        except Exception as e:
            messagebox.showerror("导出失败", f"导出时出错：\n{str(e)}")
            self.status_label.config(text="导出失败", fg="#F44336")
    
    def clear_all_students(self):
        """清空全部学生"""
        if not self.students:
            messagebox.showinfo("提示", "当前没有学生数据！")
            return
        
        # 确认清空
        result = messagebox.askyesno(
            "确认清空",
            f"确定要清空全部 {len(self.students)} 个学生的数据吗？\n\n此操作不可撤销！"
        )
        
        if result:
            self.students = []
            
            # 保存数据
            self.save_data()
            
            # 刷新表格
            self.refresh_table()
            
            self.status_label.config(text="已清空全部学生数据", fg="#F44336")
            messagebox.showinfo("完成", "已清空全部学生数据！")
    
    def save_data(self):
        """保存数据到JSON文件"""
        try:
            with open(self.data_file, 'w', encoding='utf-8') as f:
                json.dump(self.students, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"保存数据失败：{str(e)}")
    
    def load_data(self):
        """从JSON文件加载数据"""
        try:
            if self.data_file.exists():
                with open(self.data_file, 'r', encoding='utf-8') as f:
                    self.students = json.load(f)
        except Exception as e:
            print(f"加载数据失败：{str(e)}")
            self.students = []


def main():
    """主函数"""
    root = tk.Tk()
    app = StudentManagerApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()
